package com.neusoft.bizcore.web.websocket;

import java.security.Principal;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@ConditionalOnClass(WebSocketMessageBrokerConfigurer.class)
@ConditionalOnProperty(name = "bizcore.web.websocket.enable", havingValue = "true")
public class WebSocketEventListener {

    private final static String SIMP_SESSION_ID_KEY_NAME = "simpSessionId";
    private final static String SIMP_CONNECT_MESSAGE_KEY_NAME = "simpConnectMessage";
    private final static String SIMP_SESSION_ATTRIBUTES_KEY_NAME = "simpSessionAttributes";

    @Autowired
    SocketSessionRegistry webAgentSessionRegistry;

    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        final String sessionId =
                (String) event.getMessage().getHeaders().get(WebSocketEventListener.SIMP_SESSION_ID_KEY_NAME);

        @SuppressWarnings("unchecked")
        final GenericMessage<String> simpConnectMessage =
                event.getMessage().getHeaders()
                        .get(WebSocketEventListener.SIMP_CONNECT_MESSAGE_KEY_NAME, GenericMessage.class);

        @SuppressWarnings("unchecked")
        final Map<String, Object> simpSessionAttributes =
                simpConnectMessage.getHeaders()
                        .get(WebSocketEventListener.SIMP_SESSION_ATTRIBUTES_KEY_NAME, Map.class);

        final String username = ((Principal) simpSessionAttributes.get("user")).getName();
        WebSocketEventListener.log.info("a connection establishment. username is:" + username);
        this.webAgentSessionRegistry.registerSession(username, sessionId);
    }

    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        final String sessionId =
                (String) event.getMessage().getHeaders().get(WebSocketEventListener.SIMP_SESSION_ID_KEY_NAME);
        final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
        final String username = ((Principal) headerAccessor.getSessionAttributes().get("user")).getName();
        if (username != null) {
            this.webAgentSessionRegistry.unregisterSession(username, sessionId);
        }
    }
}
